package com.honeybee.cloud.framework.common.handler;

import com.alibaba.fastjson.JSONException;
import com.honeybee.cloud.framework.base.exception.ExceptionEnum;
import com.honeybee.cloud.framework.base.exception.authorize.NoAuthorizeExceptionBase;
import com.honeybee.cloud.framework.base.exception.business.BaseBizException;
import com.honeybee.cloud.framework.common.response.ResponseEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.NonTransientDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.validation.ConstraintViolationException;


/**
 * @Description 公共异常handler  api层可以继承此类，加上注解@ControllerAdvice 来达到全局处理异常的情况
 * @Author cheng
 * @Create 2018-12-08
 * @Since 1.0.0
 */
@Slf4j
public abstract class CommonExceptionHandler {

    /**
     * BindException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.error("HttpMessageNotReadableException:", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.VALIDATION_EXCEPTION));
    }
    /**
     * BindException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleBindException(BindException ex) {
        log.error("BindException:", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.SYSTEM));
    }



    /**
     * NoAuthorizeException
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(NoAuthorizeExceptionBase.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    public ResponseEntity handleBindException(NoAuthorizeExceptionBase ex) {
        log.error("NoAuthorizeException:", ex);
        return ResponseEntity.error(ex);
    }

    /**
     * Throwable  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(Throwable.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleAllException(Throwable ex) {
        log.error("Throwable:", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.SYSTEM));
    }

    /**
     * MethodArgumentNotValidException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(MethodArgumentNotValidException ex) {
        log.error("MethodArgumentNotValidException", ex);
        return ResponseEntity.error(ExceptionEnum.VALIDATION_EXCEPTION.getCode(),null,null, ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    /**
     * MissingServletRequestParameterException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(MissingServletRequestParameterException ex) {
        log.error("MissingServletRequestParameterException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.MISSING_REQUEST_PARAMETER_EXCEPTION));
    }

    /**
     * JSONException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(JSONException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(JSONException ex) {
        log.error("JSONException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.VALIDATION_EXCEPTION));
    }

    /**
     * ConstraintViolationException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(ConstraintViolationException ex) {
        log.error("ConstraintViolationException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.VALIDATION_EXCEPTION));
    }

    /**
     * ServletRequestBindingException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ServletRequestBindingException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(ServletRequestBindingException ex) {
        log.error("ServletRequestBindingException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.SYSTEM));
    }

    /**
     * HttpRequestMethodNotSupportedException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(HttpRequestMethodNotSupportedException ex) {
        log.error("HttpRequestMethodNotSupportedException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION));
    }

    /**
     * SQLException  统一只展示系统异常给前端
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(NonTransientDataAccessException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(NonTransientDataAccessException ex) {
        log.error("NonTransientDataAccessException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.SYSTEM));
    }

    /**
     * IllegalArgumentException  非法参数
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleValidateException(IllegalArgumentException ex) {
        log.error("IllegalArgumentException", ex);
        return ResponseEntity.error(BaseBizException.getInstance(ExceptionEnum.MISSING_REQUEST_PARAMETER_EXCEPTION));
    }

    /**
     * BusinessException
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(BaseBizException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity handleBindException(BaseBizException ex) {
        log.error("BusinessException:", ex);
        return ResponseEntity.error(ex);
    }
}
